package com.limanyik.family.security.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.limanyik.family.common.entity.BasisUser;
import com.limanyik.family.common.entity.server.security.UserFolderKey;
import com.limanyik.family.common.entity.server.security.UserLogin;
import com.limanyik.family.common.respcode.ResponseErrorCode;
import com.limanyik.family.common.sinterface.entity.WebUserData;
import com.limanyik.family.common.utils.*;
import com.limanyik.family.security.entity.WebLoginData;
import com.limanyik.family.security.entity.dto.UserInfoDto;
import com.limanyik.family.security.service.BasisMenusService;
import com.limanyik.family.security.service.BasisRoleService;
import com.limanyik.family.security.service.BasisUserService;
import com.limanyik.family.security.service.LoginService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Service
public class LoginServiceImpl implements LoginService {

    @Resource(name = "basisUserServiceImpl")
    BasisUserService basisUserService;

    @Resource(name = "basisRoleServiceImpl")
    BasisRoleService basisRoleService;

    @Resource(name = "basisMenusServiceImpl")
    BasisMenusService basisMenusService;

    @Autowired
    ApplicationContext applicationContext;

    /**
     * 用户信息缓存过期时间
     */
    @Value("${login.redis.time}")
    private Integer loginCacheTime;

    /**
     * cookie name
     */
    @Value("${login.cookie.name}")
    private String webLoginCookie;

    @Override
    public FamilyHttpResponse<WebLoginData> webLogin(FamilyHttpRequest<UserLogin> familyHttpRequest, HttpServletResponse response) {
        UserLogin userLogin = familyHttpRequest.getData();
        if (null == userLogin || StringUtils.isBlank(userLogin.getAccount())) {
            return FamilyHttpResponse.error(ResponseErrorCode.REGISTER_20001, "登录账号错误");
        }
        BasisUser basisUser = basisUserService.findByAccountNumber(userLogin.getAccount());
        if (null == basisUser) {
            return FamilyHttpResponse.error(ResponseErrorCode.REGISTER_20002, "不存在该账户");
        }
        // 校验用户登录信息，登录条件
        FamilyHttpResponse familyHttpResponse = verifyUserInfo(basisUser, userLogin);
        if (familyHttpResponse.getCode() != 200) {
            return familyHttpResponse;
        }
        WebUserData webUserData = new WebUserData();
        BeanUtils.copyProperties(basisUser, webUserData);
        // 设置角色信息
        webUserData = getUserRoles(webUserData);
        // 设置菜单信息
        webUserData = getUserMenus(webUserData);
        String token = setUserCache(familyHttpRequest, webUserData);
        if (StringUtils.isBlank(token)) {
            return FamilyHttpResponse.error(ResponseErrorCode.REGISTER_20006, "用户Cache设置失败");
        }
        // 设置上下文，发布事件
        applicationContext.publishEvent(webUserData);
        // 设置Cookie
        response.addCookie(new Cookie(webLoginCookie, token));
        // 登录成功,设置登录状态，返回token
        basisUser.setAccountStatus(true);
        basisUser.setLastLoginTime(LocalDateTime.now());
        basisUserService.updateById(basisUser);
        return FamilyHttpResponse.success(new WebLoginData().setToken(token));
    }

    @Override
    public BasisUser doConfigUser(String username, String password) {
        return null;
    }

    /**
     * 账号验证
     *
     * @param basisUser
     * @return
     */
    private FamilyHttpResponse verifyUserInfo(BasisUser basisUser, UserLogin userLogin) {
        if (basisUser.getDeleteStatus() != 0) {
            return FamilyHttpResponse.error(ResponseErrorCode.REGISTER_20003, "当前账号已冻结，请申请解冻");
        }
        if (!basisUser.getYourCurrentPassword().equals(ShiroMD5Util.encryption(userLogin.getPassword(), basisUser.getMobilePhone()))) {
            return FamilyHttpResponse.error(ResponseErrorCode.REGISTER_20005, "密码错误，请重试");
        }
        if (basisUser.getAccountStatus() && !basisUser.getIsNoSingleSignOn()) {
            return FamilyHttpResponse.error(ResponseErrorCode.REGISTER_20004, "当前账号已登录，是否继续");
        }
        return FamilyHttpResponse.success();
    }

    /**
     * 获取用户角色信息
     *
     * @param webUserData
     * @return
     */
    private WebUserData getUserRoles(WebUserData webUserData) {
        if (null == webUserData) {
            return new WebUserData();
        }
        webUserData.setRoles(basisRoleService.getUserRolesByUserId(new UserInfoDto().setUserId(webUserData.getId())));
        return webUserData;
    }

    /**
     * 获取用户菜单
     *
     * @param webUserData
     * @return
     */
    private WebUserData getUserMenus(WebUserData webUserData) {
        if (null == webUserData) {
            return new WebUserData();
        }
        webUserData.setMenus(basisMenusService.getUserMenusByUserId(new UserInfoDto().setUserId(webUserData.getId())));
        return webUserData;
    }

    /**
     * 设置用户缓存信息
     *
     * @param familyHttpRequest
     * @param webUserData
     * @return
     */
    private String setUserCache(FamilyHttpRequest<UserLogin> familyHttpRequest, WebUserData webUserData) {
        // 设置token
        String ip = familyHttpRequest.getIp();
        try {
            ip = ip.replace(":", "");
        } catch (Exception e) {
        }
        String token = InteriorEncryptUtil.encrypt(UUID.randomUUID().toString(), InteriorEncryptUtil.MD5);
        UserFolderKey userFolderKey = new UserFolderKey();
        userFolderKey.setIp(ip);
        userFolderKey.setToken(UserUtil.USER_TOKEN + ":" + token);

        // 判断同一个IP的用户是否存在多个token，存在则更新
        String user_folder_key = UserUtil.USER_FOLDER + ":" + webUserData.getId();
        List<UserFolderKey> userFolderKeys = (List<UserFolderKey>) UserUtil.getCache(user_folder_key);
        if (null != userFolderKeys && userFolderKeys.size() > 0) {
            boolean isUpdate = false;
            for (UserFolderKey key : userFolderKeys) {
                if (ip.equals(key.getIp())) {
                    UserUtil.delCache(key.getToken());
                    isUpdate = true;
                }
            }
            if (!isUpdate) {
                userFolderKeys.add(userFolderKey);
            }
        }
        if (null == userFolderKeys || userFolderKeys.size() <= 0) {
            userFolderKeys = new ArrayList<>();
            userFolderKeys.add(userFolderKey);
        }
        // 设置token缓存信息
        UserUtil.setCache(JSONObject.toJSON(webUserData), userFolderKey.getToken());
        // 设置用户tokens缓存信息
        UserUtil.setCache(userFolderKeys, user_folder_key);
        return token;
    }
}
